package com.eight.lesson5;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.function.IntSupplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import com.eight.lesson4.Dish;
import com.eight.lesson4.DishList;

public class NumberStreamTest {

	public static void main(String[] args) {

		System.out.println("映射到数值流：");
		int caloriesSum = DishList.getDishs().stream()
		.mapToInt(Dish::getCalories)
		.sum();
		System.out.println("总和："+caloriesSum);
		OptionalDouble caloriesAverage = DishList.getDishs().stream()
		.mapToInt(Dish::getCalories)
		.average();
		System.out.println("平均值："+caloriesAverage.getAsDouble());
		OptionalInt caloriesMax = DishList.getDishs().stream()
		.mapToInt(Dish::getCalories)
		.max();
		System.out.println("最大值："+caloriesMax.getAsInt());
		OptionalInt caloriesMin = DishList.getDishs().stream()
		.mapToInt(Dish::getCalories)
		.min();
		System.out.println("最小值："+caloriesMin.getAsInt());
		
		System.out.println("转换回对象流：");
		// 将Stream转换为数值流
		IntStream intStream = DishList.getDishs().stream().mapToInt(Dish::getCalories);
		// 将数值流转换为Stream
		@SuppressWarnings("unused")
		Stream<Integer> stream = intStream.boxed();
		
		System.out.println("OptionalInt：");
		OptionalInt max = DishList.getDishs().stream()
		.mapToInt(Dish::getCalories)
		.max();
		System.out.println("最大值（如果没有最大值默认1）："+max.orElse(1));
		
		System.out.println("数值范围：");
		IntStream evenNumbers = IntStream.rangeClosed(1, 100)
				.filter(i -> i%2==0);
		System.out.println(evenNumbers.count());
		
		System.out.println("勾股数：");
		Stream<int[]> pythagoreanTriples = IntStream.rangeClosed(1, 100).boxed()
				.flatMap(a -> IntStream.rangeClosed(a, 100)
						.filter(b -> Math.sqrt(a*a+b*b)%1==0)
						.mapToObj(b -> new int[] {a,b,(int)Math.sqrt(a*a+b*b)}));
		pythagoreanTriples.limit(5).forEach(t -> System.out.println(t[0]+","+t[1]+","+t[2]));
		System.out.println("勾股数优化：");
		Stream<double[]> pythagoreanTriples2 = IntStream.rangeClosed(1, 100).boxed()
				.flatMap(a -> IntStream.rangeClosed(a, 100)
						.mapToObj(b -> new double[] {a,b,Math.sqrt(a*a+b*b)})
						.filter(t -> t[2]%1==0)
						);
		pythagoreanTriples2.limit(5).forEach(t -> System.out.println((int)t[0]+","+(int)t[1]+","+(int)t[2]));
		
		System.out.println("由值创建流：");
		Stream<String> stream2 = Stream.of("Java 8","Lambdas","In","Action");
		stream2.map(String::toUpperCase).forEach(System.out::println);
		// 创建空流
		@SuppressWarnings("unused")
		Stream<String> emptyStream = Stream.empty();
		
		System.out.println("由数组创建流：");
		int[] numbers = {2,3,5,7,11,13};
		int sum = Arrays.stream(numbers).sum();
		System.out.println("总和："+sum);
		
		System.out.println("由文件生成流：");
		long uniqueWords = 0;
		try {
			StringBuilder filePath = new StringBuilder(new File("").getCanonicalPath());
			filePath.append(File.separator)
			.append("src")
			.append(File.separator)
			.append("com")
			.append(File.separator)
			.append("eight")
			.append(File.separator)
			.append("lesson5")
			.append(File.separator)
			.append("data.txt");
			System.out.println(filePath.toString());
			Stream<String> lines = Files.lines(Paths.get(filePath.toString()), Charset.defaultCharset());
			uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" ")))
			.distinct()
			.count();
			lines.close();
			System.out.println("不相同的单词数："+uniqueWords);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		System.out.println("由函数生成流，创建无限流：");
		System.out.println("迭代 Stream.iterate：");
		Stream.iterate(0, n -> n+2)
		.limit(10)
		.forEach(System.out::println);
		System.out.println("斐波那契元组序列：");
		Stream.iterate(new int[] {0,1}, t -> new int[] {t[1], t[0]+t[1]})
		.limit(20)
		.forEach(t -> System.out.println("("+t[0]+","+t[1]+")"));
		System.out.println("斐波那契数：");
		Stream.iterate(new int[] {0,1}, t -> new int[] {t[1], t[0]+t[1]})
		.map(t -> t[0])
		.limit(20)
		.forEach(System.out::println);
		System.out.println("生成 Stream.generate：");
		System.out.println("获取5个0-1之间的随机数");
		Stream.generate(Math::random)
		.limit(5)
		.forEach(System.out::println);
		System.out.println("Stream.generate斐波那契数：");
		IntSupplier fib = new IntSupplier() {
			int previous = 0;
			int current = 1;
			@Override
			public int getAsInt() {
				int oldPrevious = this.previous;
				int nextValue = this.previous + this.current;
				this.previous = this.current;
				this.current = nextValue;
				return oldPrevious;
			}
		};
		IntStream.generate(fib)
		.limit(10)
		.forEach(System.out::println);
	}

}
